/*
 * 测试缓冲块大小对读取速度的影响
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mount.h>

#define flush_buffer_cache() system("echo 3 > /proc/sys/vm/drop_caches")

/*1K 2K,4K,8K,16K,32K,64K,128K,256K,512K,1M,2M,4M,8M */
const int BLOCK_SIZES[] = {1<<10,1<<11,1<<12,1<<13,1<<14,1<<15,1<<16,1<<17,1<<18,1<<19,1<<20,1<<21,1<<22,1<<23};
const char *BLOCK_SIZES_FORMAT[] = {"1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K", "1M", "2M", "4M", "8M"};


/*
 * gcc -Wall -O2 -g -o mytest mytest.c
 */
int
main (int argc, char *argv[])
{
	struct timeval tm_begin, tm_end;
	int i, j, fd, iteration;
	double diff_time;
	unsigned long asize[3], size;
	double avg_size;
	double atime[3];

	fd = open(argv[1], O_RDONLY | O_NONBLOCK);
	for (i = 0; i < 14; i++)
	{
		char *buf = (char *)malloc(BLOCK_SIZES[i]);

		flush_buffer_cache();
		sleep(1);
		lseek(fd, 0, SEEK_SET);
		sleep(1);

		for (j = 0; j < 3; j++)
		{
			iteration = 0;
			gettimeofday(&tm_begin, NULL);
			do
			{
				iteration++;
				if (read(fd, buf, BLOCK_SIZES[i]) <= 0)
					goto quit;
				gettimeofday(&tm_end, NULL);
				diff_time = (tm_end.tv_sec - tm_begin.tv_sec) + (tm_end.tv_usec - tm_begin.tv_usec)/1000000.0;
			}while (diff_time < 10.0);

			asize[j] = iteration * BLOCK_SIZES[i];
			atime[j] = diff_time;
		}

		size = (asize[0]+asize[1]+asize[2])/3;
		diff_time = (atime[0]+atime[1]+atime[2])/3.0;
		printf("%lu----%s  time: %fs   ", size, BLOCK_SIZES_FORMAT[i], diff_time);

		avg_size = (double)size / (1024.0 * 1024.0); // change to MB
		if (size >= diff_time)
			printf("speed: %.4fMB/s\n", avg_size / diff_time);
		else 
			printf("speed: %.4fKB/s\n", 1024.0 * avg_size / diff_time);

		free(buf);
	}

quit:
	return 0;
}
